package com.fkjslee;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Arrays;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.fkjslee.Tool.getIpAddr;
import static com.fkjslee.Tool.uploadFile;

/**
 * @author fkjslee
 * @date 2018/5/7 at 10:25
 * Copyright (c) 2018 fkjslee. All rights reserved.
 */

@RestController
public class FileController {

    private final Logger log = LoggerFactory.getLogger(DCOPController.class);

    /**
     * client get finished file
     *
     * @return
     */
    @RequestMapping(value = "/getFinishedFileName")
    public String getFinishedFile(HttpServletResponse response, String userName) {
        response.addHeader("Access-Control-Allow-Origin", "*");
        if (userName == null)
            return "no userName";
        JSONArray result = new JSONArray();
        String filesPath = "receiveFile/" + userName;
        File[] files = new File(filesPath).listFiles();
        if (files != null) {
            for (File file : files) {
                InputStreamReader reader = null;
                BufferedReader br = null;
                try {
                    JSONObject object = new JSONObject();
                    object.put("name", file.getName());
                    reader = new InputStreamReader(new FileInputStream(file));
                    br = new BufferedReader(reader);
                    String firstLine = br.readLine();
                    Pattern pattern = Pattern.compile("(\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2})");
                    Matcher matcher = pattern.matcher(firstLine);
                    if (matcher.find())
                        object.put("time", matcher.group());
                    if (matcher.find()) { // there must be only one time format in the first line
                        try {
                            throw new Exception("the first line must only have one time" + file.getName());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    result.add(object);
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        reader.close();
                        br.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return result.toString();
    }


    /**
     * station return finished file to server
     *
     * @param file
     * @param userName
     * @return
     */
    @RequestMapping(value = "/sendFinishedFile")
    public String sendFinishedFile(MultipartFile file, String userName) {
        log.info("station send file to server, file name = {}, user name = {}", (file == null ? "no file" : file.getOriginalFilename()), userName);
        if (file == null || file.getOriginalFilename().length() == 0) return "no file";
        String fileName = file.getOriginalFilename();
        String filePath = "receiveFile/" + userName + "/";
        try {
            uploadFile(file.getBytes(), filePath, fileName.substring(0, fileName.lastIndexOf("_")), "txt");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "uploading success";
    }

    /**
     * station download zip file from server, when download is over, delete the file
     * @param res
     * @param request
     * @param fileName
     */
    @RequestMapping(value = "/downloadZipFile")
    public void downloadZipFile(HttpServletResponse res, HttpServletRequest request, String fileName) {
        downloadFile(res, request, fileName, "zip");
    }

    @RequestMapping(value = "/downloadResultFile")
    public void downloadResultFile(HttpServletResponse res, HttpServletRequest request, String fileName) {
        downloadFile(res, request, fileName, "result");
    }

    private void downloadFile(HttpServletResponse res, HttpServletRequest request, String fileName, String fileType) {
        if ("zip".equals(fileType))
            fileName = "zipFileBuffer/" + fileName;
        else
            fileName = "receiveFile/" + fileName;
        log.info("someone download file from server, ip={}, file name = {}", getIpAddr(request), fileName);
        res.setHeader("content-type", "application/octet-stream");
        res.setContentType("application/octet-stream");
        res.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        if (!new File(fileName).exists())
            return;
        byte[] buff = new byte[1024];
        BufferedInputStream bis = null;
        OutputStream os = null;
        try {
            os = res.getOutputStream();
            bis = new BufferedInputStream(new FileInputStream(new File(fileName)));
            int len = bis.read(buff);
            while (len != -1) {
                os.write(buff, 0, len);
                os.flush();
                len = bis.read(buff);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (bis != null) {
                    bis.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @RequestMapping(value = "removeFile")
    public String removeFile(String userName, String files) {
        if (userName == null || !new File("receiveFile/" + userName).isDirectory()) {
            return "{\"type\":\"error\", \"code\":\"2\", \"reason\":\"wrong account\"}";
        }
        Vector<String> failedFiles = new Vector<>();
        JSONArray jArrayFiles = JSONArray.fromObject(files);
        for (int i = 0; i < jArrayFiles.size(); ++i) {
            JSONObject jObjFile = jArrayFiles.getJSONObject(i);
            String fileName = jObjFile.getString("thFileName");
            if (fileName == null) {
                return "{\"type\":\"error\", \"code\":\"3\", \"reason\":\"wrong json format?\"}";
            }
            if (new File("receiveFile/" + userName + "/" + fileName).delete())
                log.info("account remove file success, account = {}, file name = {}", userName, fileName);
            else {
                log.error("account remove file failed, account = {}, file name = {}", userName, fileName);
                failedFiles.add(fileName);
            }
        }
        if (failedFiles.size() == 0) {
            return "{\"type\":\"success\", \"code\":\"0\"}";
        } else {
            return "{\"type\":\"failed\", \"code\": \"1\", \"reason\": \"delete failed\", \"msg\":" + Arrays.toString(failedFiles.toArray()) + "}";
        }
    }
}
